package bhwz.seac3.ui.user.graphics;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.data.time.Month;
import org.jfree.data.time.SimpleTimePeriod;
import org.jfree.data.time.TimePeriod;
import org.jfree.data.time.TimePeriodValues;
import org.jfree.data.time.TimePeriodValuesCollection;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.junit.Test;

public class Graphics {

	static {
		setTheme();
	}
	
	public static List<String> exec(String cmd){
		System.out.println(cmd);
		Runtime rt=Runtime.getRuntime();
		try {
			Process p=rt.exec(cmd);
			p.waitFor();
			BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
			ArrayList<String> result=new ArrayList<String>();
			while(true){
				String s=br.readLine();
				if(s==null)
					break;
				else
					result.add(s);
			}
			return result;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 
	 * @param names
	 * <br>
	 *            name of each attribute<br>
	 *            Attributes will be displayed clockwise
	 * @param values
	 * <br>
	 *            values of each attribute<br>
	 *            1.0 means max
	 * @return
	 */
	public static JPanel getRadarChart(String title, List<String> valueNames,
			List<Double> values, List<Double> medianValues) {
		CategoryDataset categoryDataset = makeRadarChartDataset(valueNames,
				values, medianValues);
		SpiderWebPlot spiderwebplot = new SpiderWebPlot(categoryDataset);
		spiderwebplot
				.setToolTipGenerator(new StandardCategoryToolTipGenerator());
		JFreeChart jfreechart = new JFreeChart(title, spiderwebplot);

		return getPanel(jfreechart);
	}

	public static JPanel getLineChart(String title, String valueNames,
			List<Date> dates, List<Double> values, double quartile_1,
			double quartile_2, double quartile_3, double quartile_4) {
		XYDataset xydataset = makeLineChartDataset(dates, values, quartile_1,
				quartile_2, quartile_3, quartile_4);
		JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(title, "赛季",
				valueNames, xydataset, true, true, true);
		return getPanel(jfreechart);
	}

	public static JPanel getLineChart(String title, String valueNames,
			List<String> seasons, List<Double> values, List<Double> quartile_1,
			List<Double> quartile_2, List<Double> quartile_3,
			List<Double> quartile_4) {
		XYDataset xydataset = makeLineChartDataset(seasons, values, quartile_1,
				quartile_2, quartile_3, quartile_4);
		JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(title, "赛季",
				valueNames, xydataset, true, true, true);
		return getPanel(jfreechart);
	}

	public static JPanel getPieChart(String title, List<String> valueNames,
			List<Double> values) {
		PieDataset dataset = makePieDataset(valueNames, values);
		JFreeChart chart = ChartFactory.createPieChart(title, dataset, true,
				true, false);
		return getPanel(chart);
	}

	public static JPanel getScatterChart(String title, String xName,
			List<Double> xValues, String yName, List<Double> yValues) {
		JFreeChart chart = ChartFactory.createScatterPlot(title, xName, yName,
				makeScatterDataset(xValues, yValues));
		return getPanel(chart);
	}
	
	public static Object[] getHistogram(List<Double> xValues){
		try {
			File imagefile=File.createTempFile("seac3", ".png");
			StringBuilder sb=new StringBuilder();
			sb.append("python pysrc/Histogram.py ");
			sb.append(imagefile.getAbsolutePath());
			for(Double x:xValues){
				sb.append(" ");
				sb.append(x);
			}
			List<String> output=exec(sb.toString());
			
			JPanel result=new JPanel(){
				private static final long serialVersionUID = 1L;

				@Override
				public void paint(java.awt.Graphics g) {
					super.paint(g);
					Image image=Toolkit.getDefaultToolkit().getImage(imagefile.getAbsolutePath());
					g.drawImage(image,0,0,this.getWidth(),this.getHeight(),this);
				}
			};
			return new Object[]{result,output};
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return null;
	}

	private static CategoryDataset makeRadarChartDataset(
			List<String> valuesName, List<Double> values,
			List<Double> medianValues) {
		String key_my = "我的数据";
		String key_mid = "中位数";
		String key_max = "最大值";
		double maxValue = 1.0;
		DefaultCategoryDataset data = new DefaultCategoryDataset();
		for (int i = 0; i < valuesName.size(); i++) {
			data.addValue(values.get(i), key_my, valuesName.get(i));
			data.addValue(medianValues.get(i), key_mid, valuesName.get(i));
			data.addValue(maxValue, key_max, valuesName.get(i));
		}
		return data;
	}

	private static XYDataset makeLineChartDataset(List<Date> dates,
			List<Double> values, double quartile_1, double quartile_2,
			double quartile_3, double quartile_4) {
		List<TimePeriod> times = dates.stream()
				.map(date -> new SimpleTimePeriod(date, date))
				.collect(Collectors.toList());
		TimePeriodValues mydata = makeTimePeriodValues("我的数据", times, values);
		TimePeriodValues q1data = makeTimePeriodValues("全部数据第一四分位数", times,
				quartile_1);
		TimePeriodValues q2data = makeTimePeriodValues("全部数据第二四分位数", times,
				quartile_2);
		TimePeriodValues q3data = makeTimePeriodValues("全部数据第三四分位数", times,
				quartile_3);
		TimePeriodValues q4data = makeTimePeriodValues("全部数据最大值", times,
				quartile_4);
		TimePeriodValuesCollection timeseriescollection = new TimePeriodValuesCollection();
		timeseriescollection.addSeries(mydata);
		timeseriescollection.addSeries(q1data);
		timeseriescollection.addSeries(q2data);
		timeseriescollection.addSeries(q3data);
		timeseriescollection.addSeries(q4data);
		return timeseriescollection;
	}

	private static XYDataset makeLineChartDataset(List<String> seasons,
			List<Double> values, List<Double> quartile_1,
			List<Double> quartile_2, List<Double> quartile_3,
			List<Double> quartile_4) {
		List<TimePeriod> times = parseSeasonList(seasons);
		TimePeriodValues mydata = makeTimePeriodValues("我的数据", times, values);
		TimePeriodValues q1data = makeTimePeriodValues("全部数据第一四分位数", times,
				quartile_1);
		TimePeriodValues q2data = makeTimePeriodValues("全部数据第二四分位数", times,
				quartile_2);
		TimePeriodValues q3data = makeTimePeriodValues("全部数据第三四分位数", times,
				quartile_3);
		TimePeriodValues q4data = makeTimePeriodValues("全部数据最大值", times,
				quartile_4);
		TimePeriodValuesCollection timeseriescollection = new TimePeriodValuesCollection();
		timeseriescollection.addSeries(mydata);
		timeseriescollection.addSeries(q1data);
		timeseriescollection.addSeries(q2data);
		timeseriescollection.addSeries(q3data);
		timeseriescollection.addSeries(q4data);
		return timeseriescollection;
	}

	private static XYDataset makeScatterDataset(List<Double> xValues,
			List<Double> yValues) {
		DefaultXYDataset dataset = new DefaultXYDataset();
		double[][] values = new double[2][xValues.size()];
		for (int i = 0; i < xValues.size(); i++) {
			values[0][i] = xValues.get(i);
			values[1][i] = yValues.get(i);
		}
		dataset.addSeries("default", values);
		return dataset;
	}

	private static PieDataset makePieDataset(List<String> valueNames,
			List<Double> values) {
		DefaultPieDataset defaultpiedataset = new DefaultPieDataset();
		for (int i = 0; i < valueNames.size(); i++) {
			defaultpiedataset.setValue(valueNames.get(i), values.get(i));
		}
		return defaultpiedataset;
	}

	private static TimePeriodValues makeTimePeriodValues(String name,
			List<TimePeriod> times, List<Double> values) {
		TimePeriodValues tpv = new TimePeriodValues(name);
		for (int i = 0; i < times.size(); i++) {
			tpv.add(times.get(i), values.get(i));
		}
		return tpv;
	}

	private static TimePeriodValues makeTimePeriodValues(String name,
			List<TimePeriod> times, double value) {
		TimePeriodValues tpv = new TimePeriodValues(name);
		for (int i = 0; i < times.size(); i++) {
			tpv.add(times.get(i), value);
		}
		return tpv;
	}

	private static List<TimePeriod> parseSeasonList(List<String> seasons) {
		return seasons.stream().map(season -> parseSeason(season))
				.collect(Collectors.toList());
	}

	private static TimePeriod parseSeason(String season) {
		String[] timePoint = season.split("-");
		int startYear = 2000 + Integer.parseInt(timePoint[0]);
		if (startYear > 2045) {
			startYear = startYear - 100;
		}
		int endYear = startYear + 1;
		Date start = new Month(9, startYear).getStart();
		Date end = new Month(8, endYear).getEnd();
		return new SimpleTimePeriod(start, end);
	}

	private static void setTheme() {
		// 创建主题样式
		StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
		// 设置标题字体
		standardChartTheme.setExtraLargeFont(new Font("黑体", Font.BOLD, 20));
		// 设置图例的字体
		standardChartTheme.setRegularFont(new Font("黑体", Font.BOLD, 15));
		// 设置轴向的字体
		standardChartTheme.setLargeFont(new Font("黑体", Font.BOLD, 15));
		// 应用主题样式
		ChartFactory.setChartTheme(standardChartTheme);
	}

	private static JPanel getPanel(JFreeChart chart) {
		ChartPanel panel = new ChartPanel(chart, true);
		return panel;
	}
	
	@Test
	public void testHistogram(){
		
		JFrame f=new JFrame();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setBounds(0, 0, 1000, 1000);
		f.setLayout(new BorderLayout());
		f.add((Component) getHistogram(Arrays.asList(2.0,3.0))[0],BorderLayout.CENTER);
		f.setVisible(true);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Test
	public void testScatterChart() {
		JFrame frame = new JFrame("Java数据统计图");
		frame.add(getScatterChart("散点图", "我是x",
				Arrays.asList(new Double[] { 1.0, 2.0, 3.0, 4.0, 5.0 }), "我是y",
				Arrays.asList(new Double[] { 1.0, 2.0, 3.0, 4.0, 5.0 })));
		frame.setBounds(50, 50, 800, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testPieChart() {
		JFrame frame = new JFrame("Java数据统计图");
		frame.add(getPieChart("饼图",
				Arrays.asList(new String[] { "啊", "吧", "次", "的", "额" }),
				Arrays.asList(new Double[] { 1.0, 2.0, 3.0, 4.0, 5.0 })));
		frame.setBounds(50, 50, 800, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testRadarChart() {
		JFrame frame = new JFrame("Java数据统计图");
		frame.add(getRadarChart("雷达图",
				Arrays.asList(new String[] { "啊", "吧", "次", "的", "额" }),
				Arrays.asList(new Double[] { 0.7, 0.6, 0.5, 0.4, 0.3 }),
				Arrays.asList(new Double[] { 0.5, 0.5, 0.5, 0.5, 0.5 })));
		frame.setBounds(50, 50, 800, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testAllSeasonLineChart() {
		JFrame frame = new JFrame("Java数据统计图");

		frame.add(getLineChart("全部赛季", "testData",
				Arrays.asList(new String[] { "12-13", "13-14" }),
				Arrays.asList(new Double[] { 1.0, 4.0 }),
				Arrays.asList(new Double[] { 1.0, 1.0 }),
				Arrays.asList(new Double[] { 2.0, 2.0 }),
				Arrays.asList(new Double[] { 3.0, 3.0 }),
				Arrays.asList(new Double[] { 4.0, 4.0 })));

		frame.setBounds(50, 50, 800, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testThisSeasonLineChart() {
		JFrame frame = new JFrame("Java数据统计图");
		frame.add(getLineChart(
				"本赛季",
				"testData",
				Arrays.asList(new Date[] {
						new Date(System.currentTimeMillis()),
						new Date(System.currentTimeMillis() + 100L) }),
				Arrays.asList(new Double[] { 1.0, 4.0 }), 1.0, 2.0, 3.0, 4.0));
		frame.setBounds(50, 50, 800, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
